<template>
  <div class="flex">
    <div>
      <div>
        <button @click="playVideo">播放</button>
        <button @click="pauseVideo">暂停</button>
        <label for="frameRate">帧率:</label>
        <input id="frameRate" v-model.number="frameRate" type="number" min="1" />
      </div>

      <div>
        <button @click="previousFrame">上一帧</button>
        <button @click="nextFrame">下一帧</button>
      </div>

      <div>
        <label for="gotoFrame">跳转到帧:</label>
        <input id="gotoFrame" v-model.number="gotoFrame" type="number" min="0" />
        <button @click="goToFrame">跳转</button>
        &nbsp; &nbsp; &nbsp;
        <button @click="getImg">获取图片</button>
      </div>
      <button @click="getImg">生成土拍你</button>

      <div>当前帧数: {{ currentFrame }} / 总帧数: {{ totalFrames }}</div>

      <canvas id="c" width="800" height="400"></canvas>
    </div>

    <img
      class="w-600 h-400"
      :src="`http://192.168.20.176:8777/frame1?url=https://stream7.iqilu.com/10339/article/202002/17/778c5884fa97f460dac8d90493c451de.mp4&time=${time}`"
      alt=""
    />
  </div>
  <video id="video11" width="960" height="540" crossOrigin="anonymous" muted controls style="opacity: 0">
    <source src="https://stream7.iqilu.com/10339/article/202002/17/778c5884fa97f460dac8d90493c451de.mp4" />
  </video>
</template>

<script setup lang="ts">
  import { fabric } from 'fabric'
  import { computed, onMounted, ref, watch } from 'vue'

  let canvas = ref(null)
  let videoElement = null
  let frameRate = ref(25)
  let currentFrame = ref(0)
  let totalFrames = ref(0)

  let objectsArray = ref([
    {
      frame: 20, // 帧数
      rects: [
        { left: 100, top: 100, width: 50, height: 50, fill: 'blue', stroke: 'black', strokeWidth: 2 },
        { left: 200, top: 200, width: 80, height: 60, fill: 'green', stroke: 'black', strokeWidth: 2 }
      ]
    },
    {
      frame: 70, // 帧数
      rects: [
        { left: 100, top: 100, width: 50, height: 50, fill: 'blue', stroke: 'black', strokeWidth: 2 },
        { left: 200, top: 200, width: 80, height: 60, fill: 'green', stroke: 'black', strokeWidth: 2 }
      ]
    },
    {
      frame: 90, // 帧数
      rects: [
        { left: 100, top: 100, width: 50, height: 50, fill: 'blue', stroke: 'black', strokeWidth: 2 },
        { left: 200, top: 200, width: 80, height: 60, fill: 'green', stroke: 'black', strokeWidth: 2 }
      ]
    },
    {
      frame: 108, // 帧数
      rects: [
        { left: 100, top: 100, width: 50, height: 50, fill: 'blue', stroke: 'black', strokeWidth: 2 },
        { left: 200, top: 200, width: 80, height: 60, fill: 'green', stroke: 'black', strokeWidth: 2 }
      ]
    },
    {
      frame: 220, // 帧数
      rects: [{ left: 150, top: 150, width: 70, height: 70, fill: 'red', stroke: 'black', strokeWidth: 2 }]
    }
    // 可以根据需要添加更多对象
  ])

  //是否同步刷新帧率
  let isOpenSyncTime = false

  let time = ref(0)

  let fabricCanvas: fabric.Canvas = null
  let videoFabric = null

  let getImg = () => {
    time.value = Math.round(videoElement.currentTime * 1000)
  }

  let playVideo = () => {
    videoElement.play()
  }

  let pauseVideo = () => {
    videoElement.pause()
  }

  let previousFrame = () => {
    videoElement.pause()
    let frameDuration = 1 / frameRate.value // 每帧的时间长度（假设帧率为frameRate.value）
    videoElement.currentTime = Math.max(videoElement.currentTime - frameDuration, 0)
    if (currentFrame.value > 0) {
      currentFrame.value--
    }
  }

  let nextFrame = () => {
    videoElement.pause()
    let frameDuration = 1 / frameRate.value // 每帧的时间长度（假设帧率为frameRate.value）
    videoElement.currentTime = Math.min(videoElement.currentTime + frameDuration, videoElement.duration)

    currentFrame.value++
  }

  let gotoFrame = ref(0)

  let goToFrame = () => {
    videoElement.pause()
    let frameDuration = 1 / frameRate.value // 每帧的时间长度（假设帧率为frameRate.value）
    videoElement.currentTime = Math.min(gotoFrame.value * frameDuration, videoElement.duration)
    currentFrame.value = gotoFrame.value
  }

  let renderRectangles = (rect, frame) => {
    let fabricRect = new fabric.Rect({
      left: rect.left,
      top: rect.top,
      width: rect.width,
      height: rect.height,
      fill: rect.fill,
      stroke: rect.stroke,
      strokeWidth: rect.strokeWidth,
      visible: false,
      frame
    })
    fabricCanvas.add(fabricRect)
  }

  // 定义一个函数，用于比较两个矩形对象是否相等
  function isEqualToFabricRect(obj, fabricRect) {
    if (!obj || !fabricRect) {
      return false
    }

    // 比较基本属性
    if (
      obj.left !== fabricRect.left ||
      obj.top !== fabricRect.top ||
      obj.width !== fabricRect.width ||
      obj.height !== fabricRect.height ||
      obj.fill !== fabricRect.fill ||
      obj.stroke !== fabricRect.stroke ||
      obj.strokeWidth !== fabricRect.strokeWidth
    ) {
      return false
    }

    // 如果需要比较更多的属性，可以继续添加

    return true
  }

  onMounted(async () => {
    fabricCanvas = new fabric.Canvas('c')
    videoElement = document.querySelector('#video11')

    /* ---------------------------- */
    objectsArray.value.forEach(it => {
      it.rects.forEach(rect => renderRectangles(rect, it.frame))
    })
    /* ---------------------------- */

    const scaleX = 800 / 960
    const scaleY = 400 / 540
    const minScale = Math.min(scaleX, scaleY)

    videoFabric = new fabric.Image(videoElement, {
      left: 0,
      top: 0,
      scaleX: minScale,
      scaleY: minScale
    })

    fabricCanvas.add(videoFabric)
    fabricCanvas.sendToBack(videoFabric) // 将 fabricRect 置于最后面

    videoElement.addEventListener('loadedmetadata', () => {
      totalFrames.value = Math.floor(videoElement.duration * frameRate.value)
      console.log('video metadata ---- ', videoElement.videoWidth, videoElement.videoHeight)
    })

    videoElement.addEventListener('play', () => (isOpenSyncTime = true))
    videoElement.addEventListener('pause', () => (isOpenSyncTime = false))

    fabric.util.requestAnimFrame(function render() {
      // console.log('videoElement.currentTime)', videoElement.currentTime)

      if (isOpenSyncTime) {
        currentFrame.value = Math.floor(videoElement.currentTime * frameRate.value) // 更新当前帧数
      }

      console.log('   currentFrame.value', currentFrame.value)

      /* ---------------------------- */
      const objs = fabricCanvas.getObjects()
      objs.forEach(obj => {
        if (!(obj instanceof fabric.Rect)) {
          return
        }

        console.log('frame', obj.frame)

        obj.visible = obj.frame === currentFrame.value
      })
      /* ---------------------------- */

      fabricCanvas.renderAll()
      fabric.util.requestAnimFrame(render)
    })
  })
</script>

<style>
  canvas {
    border: 1px solid #000;
  }
</style>
